<?php

define(VAS_USER_AGENT,"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121621 Ubuntu/8.04 (hardy) Firefox/3.0.5");
define(FDMS_LOGIN_URL, "http://keystone.aldorsolutions.com/webfdms/processLogon.do");
define(FDMS_VITALS_PAGE_URL, "http://keystone.aldorsolutions.com/webfdms/showVitals.do");
define(FDMS_VITALS_UPDATE_URL, "http://keystone.aldorsolutions.com/webfdms/processVitals.do");
define(VAS_VITALS_UPDATE_URL, "/vasapplyVitals.php");

require_once("HTTP/Client.php");
require_once("HTTP/Request.php");

//*********************************************************************************
//  page scraper to auto-login to FDMS so we can go get the vital stats page
//*********************************************************************************

//*********************************************************************************
function get_jsessionid( $req )
{
    $cookies = $req->getResponseCookies();
    $jsessionid = $cookies[0]['value'];
    return $jsessionid;
}

//*********************************************************************************
// analyzes the body of the page returned from the FDMS login attempt.  it can be
// a login page, or it can be the main menu page, or it can be something else.
function analyze_returned_FDMS_page( $html_page )
{
    $results = array();
    
    $dom = new DomDocument();

    $old_level = error_reporting();
    error_reporting( E_NOTICE );
    $dom->loadHTML( $html_page );
    error_reporting( $old_level );
    
    // FDMS catches things like expired users and duplicate user logins and
    // sends them back to the browser (and the Javascript code) as values of
    // hidden fields.

    // master result -- whether or not we got past the login page
    $results['logged_in'] = false;

    // error codes sent back via javascript form
    $results['duplicate_user'] = false;
    $results['expired_user'] = false;
    $results['expiring_user'] = false;
    $results['expiration_interval'] = 0;
    $results['invalid_creds'] = false;
    $results['misc_error'] = false;

    // get title to tell us which page we're in
    $title = $dom->getElementsByTagName("title")->item(0)->nodeValue;

    // if we're in the login page, we tried to log in and were refused
    if($title == "FDMS Network Login")
    {
        $loc = "login";

        $invalidCreds = false;

        $contentDiv = $dom->getElementById("content");
        $divText = $contentDiv->textContent;
        if(stristr($divText, "Invalid username"))
        {
            $invalidCreds = true;
        }
        
        $dupeUserErr = "";
        $expiringUserWarning = "";
        $expiryInterval = "";
        $submitValue = "";
        
        $forms = $dom->getElementsByTagName("form");
        $inputs = $dom->getElementsByTagName("input");
        $num_inputs = $inputs->length;
        for($i=0; $i<$num_inputs; $i++)
        {
            $inputNode = $inputs->item($i);
            if($inputNode->hasAttributes())
            {
                $inputName = $inputNode->getAttribute("name");
                if($inputName == "duplicateUserError")
                {
                    $dupeUserErr = $inputNode->getAttribute("value");
                }

                if($inputName == "expirationDateWarning")
                {
                    $expiringUserWarning = $inputNode->getAttribute("value");
                }

                if($inputName == "expirationInterval")
                {
                    $expiryInterval = $inputNode->getAttribute("value");
                }

                if($inputName == "submitButton")
                {
                    $submitValue = $inputNode->getAttribute("value");
                }
            }
        }

        // now check the flags we got to see what the page says is happening
        if($invalidCreds)       // page says bad username/password
        {
            $results['invalid_creds'] = true;
        }
        else
        if($dupeUserErr == "true")  // correct creds, but user already logged in
        {
            $results['duplicate_user'] = true;
        }
        else
        if($expiringUserWarning == "true")
        {
            // check interval to see if user has expired or is about to expire
            if($expiryInterval < 1)
            {
                // user has expired
                $results['expired_user'] = true;
            }
            else
            {
                // user is close to expiring
                $results['expiring_user'] = true;
                $results['expiration_interval'] = $expiryInterval;
            }
        }
        else
        {
            $results['misc_error'] = true;
        }
    }
    else
    if($title == "FDMS Network Main Menu")
    {
        $loc = "main_menu";
        $results['logged_in'] = true;
    }

    $results['location'] = $loc;

    return $results;
}

//*********************************************************************************
// formulates and sends a POST request and analyzes the returned page
function perform_FDMS_login_request( $url, $jsessionid, $uname, $passwd, $options )
{
    $post_req =& new HTTP_Request($url);
    $post_req->setMethod(HTTP_REQUEST_METHOD_POST);

    // these things are *always* here.
    $post_req->addPostData("username", $uname);
    $post_req->addPostData("password", $passwd);
    $post_req->addCookie("JSESSIONID", $jsessionid);

    foreach( $options as $optionKey=>$optionValue)
    {
        $post_req->addPostData( $optionKey, $optionValue );
    }
    
    if (!PEAR::isError($post_req->sendRequest())) {

        $error_code = $post_req->getResponseCode();
        $returned_page = $post_req->getResponseBody();

        // now analyze the body of the response to see if:
        $results = analyze_returned_FDMS_page( $returned_page );
        $results['http_result_code'] = $error_code;
    } 
    else
    {
        $error_code = $post_req->getResponseCode();
        $jsessionid = "";

        $results = array();
        $results['http_result_code'] = $error_code;
    }

    return $results;
}

//*********************************************************************************
// masterminds the login request and handles re-posting if one of FDMS's odd
// results comes back
function keystone_FDMS_login( $uname, $passwd )
{
    $error_code = 200;
    $logged_in = false;

    $url = FDMS_LOGIN_URL;
    
    // first, fetch the login page and capture the session id it generates
    $get_req =& new HTTP_Request($url);
    $get_req->setMethod(HTTP_REQUEST_METHOD_GET);

    if (!PEAR::isError($get_req->sendRequest())) {
        $jsessionid = get_jsessionid($get_req);
        $error_code = $get_req->getResponseCode();
    } else {
        $error_code = $get_req->getResponseCode();
        $jsessionid = "";
    }

    // now make a POST request using the JSESSIONID.  use the username and
    // password.
    if($error_code == 200)
    {
        $options = array();

        // start off optimistic
        $options['duplicateUserError'] = false;
        $options['expirationDateWarning'] = false;
        $options['browser'] = "Netscape";
        $options['userAgent'] = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121621 Ubuntu/8.04 (hardy) Firefox/3.0.5";
        $options['submitButton'] = "login";
    
        $results = perform_FDMS_login_request( $url, $jsessionid, $uname, $passwd, $options );
        if($results['logged_in'])
        {
            $results['status'] = "Logged in";
            $results['status_reason'] = "No problems.";
            $logged_in = true;            
        }
        else
        {            
            $logged_in = false;
            $results['status'] = "Not logged in";
            
            if($results['logged_in'])
            {
                // hunky dory
            }
            else
            {
                if($results['duplicate_user'])
                {
                    // set $options["submitButton"] = "proceed" and redo the request
                    $options["submitButton"] = "proceed";
                    $results = perform_FDMS_login_request( $url, $jsessionid, $uname, $passwd, $options );
                    $results['status'] = "Logged in";
                    $results['status_reason'] = "Logged in after duplicate user disconnected.";
                }
                else
                if($results['expired_user'])
                {
                    // bounce out with a message
                    $results['status'] = "Not logged in";
                    $results['status_reason'] = "User account '$uname' is expired.";
                }
                else
                if($results['expiring_user'])
                {
                    // set $options["submitButton"] to "proceed" and redo the
                    // request, but add a message that the user is expiring.
                    $options["submitButton"] = "warning";
                    $results = perform_FDMS_login_request( $url, $jsessionid, $uname, $passwd, $options );
                    $results['status'] = "Logged in";
                    $results['status_reason'] = "Logged in, but user account '$uname' is expiring soon.";
                }
                else
                if($results['invalid_creds'])
                {
                    // bounce out with a message
                    $results['status'] = "Not logged in";
                    $results['status_reason'] = "Username and/or password supplied is not valid.";
                }
                else
                {
                    // catch-all - bounce out with a nonspecific error message
                    $results['status'] = "Not logged in";
                    $results['status_reason'] = "Error logging in.  Please contact tech support.";
                }
            }
        }
    }
    else
    {
        // got back a non-OK result code.  set status and status_resaon in $results[]
        $results = array();
        $results['status'] = "Not logged in";
        $results['status_reason'] = "Error logging in.  Please contact tech support.";
    }
    
    $results['jsessionid'] = $jsessionid;
    $results['location'] = $loc;
    $results['logged_in'] = $logged_in;
    $results['error'] = $error_code;

    return $results;
}

//********************************************************************************
// may need to modify this one to replace the form's action script with one of our
// own.
//********************************************************************************

function check_FDMS_vitalsPage( &$page, &$results )
{
    $dom = new DomDocument();

    $old_level = error_reporting();
    error_reporting( E_NOTICE );
    $dom->loadHTML( $page );
    error_reporting( $old_level );

	$page_sections = array();
	
	$domHEAD = new DomDocument();
	$domBODY = new DomDocument();
		
	$doc_head = $dom->getElementsByTagName("head");	
	
	$head = $doc_head->item(0)->cloneNode(true);

	$head = $domHEAD->importNode( $head, true );

	$head_children = $head->childNodes;
	
	$links = array();
	$scripts = array();
	
	foreach( $head_children as $child_node )
	{
		$nodeName = $child_node->nodeName;
		// remove this because it messes up our javascript/dojo stuff
		/*
		if(!strcasecmp($nodeName,"base"))
		{
			$head_html_fragment .= "<base";
			if(null != $child_node->attributes)
			{
				$head_html_fragment .= " ";
				foreach( $child_node->attributes as $attrKey => $attValue )
				{
					$attrName = $attValue->name;
					$attrValue = $attValue->value;
					$head_html_fragment .= " $attrName = \"$attrValue\"";
				}
			}
			$head_html_fragment .= ">\n";
		}
		else
		*/
		
		if(!strcasecmp($nodeName, "script"))
		{
			// if we wanted to be sophisticated we'd make sure the whole aldorsolutions
			// URL was in the src attribute
			
			$script = array();
			$script['attrs'] = array();
			$script['content'] = null;
			if(null != $child_node->attributes)
			{
				foreach( $child_node->attributes as $attrKey => $attValue )
				{
					$attrName = $attValue->name;
					$attrValue = $attValue->value;
					if(strcasecmp($attrName, "src"))
					{
						// make sure we add the http://keystone.aldorsolutions.com
					}
					$script['attrs'][$attrName] = $attrValue;
				}
			}
			
			// script tag that we need
			$script['content'] .= $child_node->textContent;
			
			$scripts[] = $script;
		}
		else
		if(!strcasecmp($nodeName, "link"))
		{
			$link = array();
			$link['attrs'] = array();
			// link tag (for style sheet) that we need
			if(null != $child_node->attributes)
			{
				foreach( $child_node->attributes as $attrKey => $attValue )
				{
					$attrName = $attValue->name;
					$attrValue = $attValue->value;
					$link['attrs'][$attrName] = $attrValue;
				}
			}
			$links[] = $link;
		}
	}

	// for the body section it's a little different.  we need to grab the <body>..</body>, tags included, and bring it into
	// a DomDocument.  we *then* look for the form, modify the action script, and turn it back into HTML (and then strip out
	// the <body></body> tags.
	
	$iBodyBegin = stripos( $page, "<body" );
	$iBodyEnd = stripos( $page, "</body>" );
	$body_html = substr( $page, $iBodyBegin, $iBodyEnd + 6 - $iBodyBegin + 1 );
	
	$body_html = preg_replace( '/action=\".*\"/i', 'action="http://www.aldordemo.com/index/vasvitals"', $body_html);
	$body_html = preg_replace( '/<body.*>/i', '', $body_html );
	$body_html = preg_replace( '/<\/body>/i', '', $body_html );
	
	// radical thought -- to get our outer form POST button to work, should we 
	// delete the <form> and </form> tags?  if we do, we'll need to change the action
	// script in our main form
	$body_html = preg_replace( '/<form.*>/i', '', $body_html );
	$body_html = preg_replace( '/<\/form>/i', '', $body_html );
	
    // the checking here is simpler - just look at the title to see what
    // it says.
    $title = $dom->getElementsByTagName("title")->item(0)->nodeValue;
    
//    $forms->item(0)->setAttribute( "action", "http://localhost/keystone/VASapplyVitals.php" );
    
	$results['head_links'] = $links;
	$results['head_scripts'] = $scripts;
	
	$results['body'] = $body_html;
		
    // if we're in the login page, we tried to log in and were refused
    if($title == "Vital Statistics")
    {
        $in_vitals = true;
    }
    else
    {
        $in_vitals = false;
    }

//    $page = $dom->saveHTML();
//    $form = $forms->saveHTML();
	
    return $in_vitals;
}

function fetch_FDMS_vitalsPage( $vitalsId, $jsessionid )
{
    $results = array();

    $url= FDMS_VITALS_PAGE_URL."?vitalsId=$vitalsId";
    
    $cookies = 'cookies';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, VAS_USER_AGENT);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
    curl_setopt($ch, CURLOPT_COOKIE, "JSESSIONID=$jsessionid");

    $res = curl_exec($ch);
    $error = curl_error($ch);

    if( $error != "" )
    {
        $results['status'] = "CURL_error";
        $results['status_reason'] = curl_error($ch);
    }
    else
    {
        $info = curl_getinfo($ch);
        $code = $info['http_code'];

        if($code >= 200 && $code < 300 )
        {
            // nominally a good error code, so go examine the HTML
            // for its title.
            
            $results['status'] = "OK";
            $results['http_code'] = $code;
			
			$page_bits = null;
            if(check_FDMS_vitalsPage($res, $page_bits))
                $results['in_vitals_page'] = "yes";
            else
                $results['in_vitals_page'] = "no";
			
            $results['html'] = $res;
			$results['page_head'] = $page_bits['head'];
			$results['page_body'] = $page_bits['body'];
        }
        else
        if($code >= 300 && $code < 400 )
        {
            // redirect of some sort
            $results['status'] = "FAIL";
            $results['in_vitals_page'] = "no";
            $results['http_code'] = $code;
        }
        else
        {
            // HTTP error of some sort.
            $results['status'] = "FAIL";
            $results['in_vitals_page'] = "no";
            $results['http_code'] = $code;
        }
    }

    curl_close($ch);
    
    return $results;
}

//TODO - CURLOPT_POSTFIELDS <- $_POST[] array
//       CURLOPT_POST <- TRUE
//       for function to proxy update the FDMS vital stats table

function update_FDMS_vitalsPage( $jsessionid, $postvars )
{
    $results = array();

    $url= FDMS_VITALS_UPDATE_URL;

	$postvars["directive"] = "change";

    $cookies = 'cookies';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, VAS_USER_AGENT);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
    curl_setopt($ch, CURLOPT_COOKIE, "JSESSIONID=$jsessionid");

    $res = curl_exec($ch);
    $error = curl_error($ch);

    if( $error != "" )
    {
        $results['status'] = "CURL_error";
        $results['status_reason'] = curl_error($ch);
    }
    else
    {
        $info = curl_getinfo($ch);
        $code = $info['http_code'];

        if($code >= 200 && $code < 300 )
        {
            $results['status'] = "OK";
            $results['http_code'] = $code;
            if(stristr("<title>Case Status", $res))
                $results['success'] = "yes";
            else
                $results['success'] = "no";
            $results['html'] = $res;
        }
        else
        if($code >= 300 && $code < 400 )
        {
            // redirect of some sort
            $results['status'] = "FAIL";
            $results['success'] = "no";
            $results['http_code'] = $code;
        }
        else
        {
            // HTTP error of some sort.
            $results['status'] = "FAIL";
            $results['success'] = "no";
            $results['http_code'] = $code;
        }
    }

    curl_close($ch);

    return $results;
}
?>
